package org.deng.learn.lambda;

import java.util.*;
import java.util.concurrent.ForkJoinPool;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * @author 邓力宾
 * @date 2020/12/17 16:23
 * @desc
 */
public class StreamDemo {
    public static void main(String[] args) {
        //m1();
        //m3();
        //m4();
        //m5();
        m6();
    }

    /**
     * 流操作
     */
    public static void m1(){
        int[] nums = {1, 2, 3};
        int sum = IntStream.of(nums).sum();
        System.out.println(sum);
        sum = IntStream.of(nums).map(i -> i * 2).sum();
        System.out.println(sum);

        sum = IntStream.of(nums).map(StreamDemo::doubleNum).sum();
        System.out.println(sum);

        System.out.println(nums[0]);
        System.out.println(nums[1]);
        System.out.println(nums[2]);

    }

    /**
     * 流的创建
     */
    public static void m2(){
        //从集合创建
        List<String> list = new ArrayList<>();
        list.stream();
        list.parallelStream(); //并行流

        //从数组创建
        Arrays.stream(new int[]{1, 2, 3});

        //创建数字流
        IntStream.of(1,2, 3);
        IntStream.rangeClosed(1, 10);

        //使用random创建一个无限流
        new Random().ints().limit(10);
        Random random = new Random();

        //自己产生流
        Stream.generate(()->random.nextInt()).limit(20);
    }

    /**
     * 中间（惰性）操作 生成新的流
     */
    public static void m3(){
        String  str = "my name is 007";
        //1.map操作 把每个单词的长度打印出来
        Stream.of(str.split(" ")).map(s->s.length()).forEach(System.out::println);

        //2.过滤操作
        Stream.of(str.split(" ")).filter(s-> s.length() > 2).forEach(System.out::println);

        //3.flatMap A下有b属性，b是个集合，最终得到所有b
        //IntStream/LongStream并不是Stream的子类，所以要进行装箱boxed
        Stream.of(str.split(" ")).flatMap(s->s.chars().boxed()).forEach(i -> System.out.println((char) i.intValue()));

        //4.peek用于debug 类似于forEach,只是peek是中间操作，forEach是终止操作

        Stream.of(str.split(" ")).peek(System.out::println).forEach(System.out::println);

        //5.limit 主要用于无限流
        new Random().ints().filter(i-> i > 10 && i < 100).limit(10).forEach(System.out::println);
    }

    /**
     * 终止操作
     */
    public static void m4(){
        String  str = "my name is 007";
        str.chars().parallel().forEach(i-> System.out.print((char)i)); //无序
        System.out.println();
        str.chars().parallel().forEachOrdered(i-> System.out.print((char)i)); //有序
        System.out.println();

        //collect收集到List
        List<String> list = Stream.of(str.split(" ")).collect(Collectors.toList());
        System.out.println(list);


        //reduce 归一操作
        Optional<String> optional = Stream.of(str.split(" ")).reduce((s1, s2) -> s1 + "-" + s2);
        System.out.println(optional.orElse(""));

        String r = Stream.of(str.split(" ")).reduce("", (s1, s2) -> s1 + "-" + s2);
        System.out.println(r);

        //求单词个数
        Optional<Integer> reduce = Stream.of(str.split(" ")).map(ch -> 1).reduce((i1, i2) -> i1 + i2);
        System.out.println(reduce.get());

        long count = Stream.of(str.split(" ")).count();
        System.out.println("count："+count);


        //求最大
        Optional<String> max = Stream.of(str.split(" ")).max(Comparator.comparingInt(String::length));
        System.out.println(max.get());

        //短路操作 获取第一个
        Optional<String> first = Stream.of(str.split(" ")).findFirst();
        System.out.println(first.get());

    }

    /**
     * 并行流
     */
    public static void m5(){
        //使用自己的线程池 默认使用 ForkJoinPool.commonPool()

        ForkJoinPool pool = new ForkJoinPool(5);
        pool.submit(()->IntStream.range(1, 100).parallel().peek(i-> System.out.println(Thread.currentThread().getName()+":"+i)).count());
        pool.shutdown();
        synchronized (pool){
            try {
                pool.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static int doubleNum(int i){
        return i * 2;
    }

    public static void m6(){
        //filter是中间操作(只有中间操作没有终止操作，中间操作不会执行)
        IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).filter(i -> {
            System.out.println("filter:"+i);
            return i > 1;
        }).forEach(i-> System.out.println("forEach:"+i));

        int max = IntStream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).filter(i -> {
            System.out.println("filter:" + i);
            return i > 1;
        }).max().getAsInt();
        System.out.println(max);
    }
}
